<template>
  <div>
    <!-- 导航栏 -->
    <van-nav-bar title="搜索中心" left-arrow @click-left="$router.back()" />
    <!-- 搜索框 Vant search 提供的方法  @search按下回车点击搜索触发 .trim Vue提供的修饰符 用户去除两边空格(防止用户在两边输入空格)
          绑定 @input功能 只要用户开始搜索 就触发-->
    <van-search @input="keywordList" @search='handleSearch' v-model.trim="q" placeholder="请输入搜索关键词" shape="round" />
    <!-- 通过v-if v-else 判断 如果有输入内容 就切换成联想列表 没有输入内容就显示历史记录 -->
    <!-- 联想列表 -->
    <van-cell-group class="suggest-box" v-if='q'>
      <!-- 携带点击搜索结果的详细条目信息 -->
      <van-cell v-for="(items,index) in keylist" :key="index" icon="search">
        <!-- 使用v-html 实现样式也能打印出来 -->
        <p v-html="items"></p>
        <!-- <p>{{items}}</p> -->
      </van-cell>
    </van-cell-group>
    <!-- 搜索历史 -->
    <!-- v-else-if判断 如果存在搜索数据 才会显示内搜索记录  否则就不显示搜索记录 -->
    <div class="history-box" v-else-if="history.length">
      <div class="head">
        <span>历史记录</span>
        <!-- ? 绑定删除全部搜索历史的方法 -->
        <van-icon @click='deleteAll' name="delete"></van-icon>
      </div>
      <van-cell-group>
        <van-cell v-for="(item,index) in history" :key="index">
          <!-- 设置鼠标点击搜索历史进行跳转 注意为了防止冒泡行为 需要设置 .stop阻止冒泡行为 -->
          <a @click.stop="handleJump(item)" class="word_btn">{{item}}</a>
          <!-- ? 绑定删除指定历史条目的方法 -->
          <van-icon @click='deleteSingle(index)' class="close_btn" slot="right-icon" name="cross" />
        </van-cell>
      </van-cell-group>
    </div>
  </div>
</template>
<script>
//! 导入搜索接口的api
import { searchList } from '../../api/search'
export default {
  name: 'Search',
  data () {
    return {
      // 搜索关键字(搜索框里面的内容)
      q: '',
      // ~ 历史关键字保存对象
      // ~ 给历史关键字保存获取本地缓存的搜索数据 让其循环遍历到页面上
      // ~ 3. 读取永久储存 localStorage的搜索缓存 缓存数据是字符串 需要转成对象
      history: JSON.parse(localStorage.getItem('search') || '[]'), // ~ 如果没有值 让其显示为空的字符串数组
      //! 创建一个空对象 服务器返回的搜索数据
      keylist: [],
      //! 创建一个函数防抖函数 默认为空null(对象存储起来 用于删除防抖定时)
      timer: null
    }
  },
  methods: {
    //! 搜索功能的实现
    keywordList () {
      //! 添加搜索的 函数防抖(利用定时器 在一定时间内向服务器发送一次指令 防止频繁发送指令给服务器)
      //! 1. 当数据传入过来的时候 重置(清除)上一个防抖定时器
      clearTimeout(this.timer)
      //! 2. 防止用户输入空格搜索 trim()方法取消首尾空格后 没有数据 取反返回true 如果为true return 跳出方法
      if (!this.q.trim()) return
      //! 3. 创建一个防抖函数(定时器)
      this.timer = setTimeout(async () => { //! 5. 需要设置async同步
        //! 6. 向服务器发送数据
        const ret = await searchList(this.q)
        //! 7. 把服务器传回的值 保存到页面搜索数据里 用于打印到页面上
        // 需求：让列表项内容与关键自匹配后高亮（包裹一层span标签）
        this.keylist = ret.data.options.map(item => {
          //! 8. 全文查找、忽略大小写 匹配输入框输入的内容
          const reg = new RegExp(this.q, 'ig')
          //! 9. 通过replace()替换方法 把匹配数据 替换成高亮样式 并返回给map() 替换当前搜索数据
          return item.replace(reg, `<span>${this.q}</span>`)
        })
      }, 1000) //! 每隔一秒钟 触发一次(向服务器发送数据)
    },
    // ~ 回车搜索的配置(同时保存其历史记录)
    handleSearch () {
      // ~ 1. 防止用户输入空格搜索 trim()方法取消首尾空格后 没有数据 取反返回true 如果为true return 跳出方法
      if (!this.q.trim()) return
      // ~ 2. 回车触发后 保存历史关键字
      // ~ 把输入的内容 保存到历史关键字对象里 unshift会把数据添加到第一项 push是默认添加到结尾
      this.history.unshift(this.q)
      // ~ 3. 进行搜索数据的去重 new Set() 方法去重后自动生成数组 把没有重复的数组覆盖到 原先数组中
      this.history = [...new Set(this.history)]
      // ~ 4. 把保存历史关键字对象 把历史数据 永久存储到浏览器
      localStorage.setItem('search', JSON.stringify(this.history))
      // 回车跳转到搜索列表页面(动态路由设置) /? 也是一种路由跳转传递参数的设置
      this.$router.push({
        name: 'myresult', // name是该路径的别名 需要给路由组件设置一样名称 作用跟path一样 动态跳转
        query: { // 利用 query 动态路由跳转方法 携带数据 跳转到二级路由上
          // 携带搜索关键字的数据 左边属性名 需要和 设置的?后面路径一致 右边是要携带的属性值
          kw: this.q
        }
      })
    },
    // ? 删除搜索单个条目
    deleteSingle (index) { // ? 获取其索引值 进行删除
      // ? 在页面数据历史记录  找到指定索引 进行删除
      this.history.splice(index, 1)
      // ? 在浏览器缓存中删除(重新把页面数据覆盖到浏览器缓存中)
      localStorage.setItem('search', JSON.stringify(this.history))
    },
    // ? 删除全部搜索内容
    deleteAll () {
      // ? 清空页面数据历史记录(清除所有记录)
      this.history = []
      // ? 清空浏览器缓存中的数据
      localStorage.removeItem('search')
    },
    // 搜索联想 点击跳转到搜索页面方法(动态路由的处理)
    handleJump (kw) {
      // kw此时包括span高亮的标签，需要去掉
      const reg = new RegExp(`<span>${this.q}</span>`, 'ig')
      kw = kw.replace(reg, this.q) // 替换方法 replace(替换的规则,需要替换的数据)
      this.$router.push({
        name: 'myresult', // name是该路径的别名 需要给路由组件设置一样名称 作用跟path一样 动态跳转
        query: { // 利用 query 动态路由跳转方法 携带数据 跳转到二级路由上
          // 携带搜索关键字的数据 左边属性名 需要和 设置的?后面路径一致 右边是要携带的属性值
          kw: kw
        }
      })
    }
  }
}
</script>
<style scoped lang='less'>
.history-box {
  padding: 0 20px;
  .head {
    line-height: 36px;
    color: #999;
    .van-icon {
      font-size: 16px;
      float: right;
      margin-top: 10px;
    }
  }
  .van-cell {
    padding: 10px 0;
  }
  .word_btn {
    color: #3296fa;
  }
  .close_btn {
    margin-top: 5px;
    color: #999;
  }
}
.suggest-box {
  /deep/ .van-cell {
    padding: 10px 20px;
    color: #999;
    p {
      span {
        color: red;
      }
    }
  }
}
</style>
